import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Pay from 'wechatpay-node-v3';

/**
 * 微信支付服务
 */
@Injectable()
export class WechatPayService {
  private payment: any;

  constructor(private readonly configService: ConfigService) {
    const wechatConfig = this.configService.get('payment.wechat');

    // 初始化微信支付SDK
    this.payment = new Pay({
      appid: wechatConfig.appId,
      mchid: wechatConfig.mchId,
      publicKey: wechatConfig.publicKey,
      privateKey: wechatConfig.privateKey,
    });
  }

  /**
   * 创建Native支付（扫码支付）
   */
  async createNativePay(params: {
    outTradeNo: string;
    totalAmount: number;
    description: string;
  }) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.transactions_native({
      appid: wechatConfig.appId,
      mchid: wechatConfig.mchId,
      description: params.description,
      out_trade_no: params.outTradeNo,
      notify_url: wechatConfig.notifyUrl,
      amount: {
        total: Math.round(params.totalAmount * 100), // 微信金额单位为分
      },
    });

    return result;
  }

  /**
   * 创建H5支付（移动网页支付）
   */
  async createH5Pay(params: {
    outTradeNo: string;
    totalAmount: number;
    description: string;
  }) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.transactions_h5({
      appid: wechatConfig.appId,
      mchid: wechatConfig.mchId,
      description: params.description,
      out_trade_no: params.outTradeNo,
      notify_url: wechatConfig.notifyUrl,
      amount: {
        total: Math.round(params.totalAmount * 100),
      },
      scene_info: {
        payer_client_ip: '127.0.0.1',
        h5_info: {
          type: 'Wap',
        },
      },
    });

    return result;
  }

  /**
   * 创建JSAPI支付（公众号/小程序支付）
   */
  async createJsapiPay(params: {
    outTradeNo: string;
    totalAmount: number;
    description: string;
    openid: string;
  }) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.transactions_jsapi({
      appid: wechatConfig.appId,
      mchid: wechatConfig.mchId,
      description: params.description,
      out_trade_no: params.outTradeNo,
      notify_url: wechatConfig.notifyUrl,
      amount: {
        total: Math.round(params.totalAmount * 100),
      },
      payer: {
        openid: params.openid,
      },
    });

    return result;
  }

  /**
   * 验证微信支付回调签名
   */
  async verifyNotify(headers: any, body: any): Promise<boolean> {
    try {
      // 微信支付的签名验证
      const wechatConfig = this.configService.get('payment.wechat');
      const result = await this.payment.verifySign({
        headers,
        body,
        publicKey: wechatConfig.publicKey,
      });
      return result;
    } catch {
      return false;
    }
  }

  /**
   * 解密回调数据
   */
  async decryptNotify(
    ciphertext: string,
    nonce: string,
    associatedData: string,
  ) {
    const wechatConfig = this.configService.get('payment.wechat');
    return await this.payment.decipher_gcm(
      ciphertext,
      nonce,
      associatedData,
      wechatConfig.apiV3Key,
    );
  }

  /**
   * 查询订单
   */
  async queryOrder(outTradeNo: string) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.query({
      mchid: wechatConfig.mchId,
      out_trade_no: outTradeNo,
    });

    return result;
  }

  /**
   * 关闭订单
   */
  async closeOrder(outTradeNo: string) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.close({
      mchid: wechatConfig.mchId,
      out_trade_no: outTradeNo,
    });

    return result;
  }

  /**
   * 退款
   */
  async refund(params: {
    outTradeNo: string;
    outRefundNo: string;
    refundAmount: number;
    totalAmount: number;
    reason?: string;
  }) {
    const wechatConfig = this.configService.get('payment.wechat');

    const result = await this.payment.refunds({
      out_trade_no: params.outTradeNo,
      out_refund_no: params.outRefundNo,
      notify_url: wechatConfig.notifyUrl,
      amount: {
        refund: Math.round(params.refundAmount * 100),
        total: Math.round(params.totalAmount * 100),
        currency: 'CNY',
      },
      reason: params.reason || '用户申请退款',
    });

    return result;
  }

  /**
   * 查询退款
   */
  async queryRefund(outRefundNo: string) {
    const result = await this.payment.find_refunds({
      out_refund_no: outRefundNo,
    });

    return result;
  }
}
